import { sm2 } from "sm-crypto";
import { getSM2Config } from "@/api/sm2"; // 通过接口获取加解密的配置

// 加密策略，1 - C1C3C2，0 - C1C2C3，默认为1
let encryptMode = 1;
// 通过环境变量env配置 STATIC 代表使用 VITE_PUBLIC_KEY，VITE_PRIVATE_KEY 密钥key, 反之需要通过接口去拿密钥key
let publicKey =
  import.meta.env.VITE_ENCRYPT_KEY === "STATIC"
    ? import.meta.env.VITE_PUBLIC_KEY
    : "";
let privateKey =
  import.meta.env.VITE_ENCRYPT_KEY === "STATIC"
    ? import.meta.env.VITE_PRIVATE_KEY
    : "";

// 加密配置开关 ENCRYPTION 代表开启加解密
export const ENCRYPT = import.meta.env.VITE_ENCRYPT === "ENCRYPTION";

/**
 * 获取加解密配置
 * @returns encryptMode 加密策略，1 - C1C3C2，0 - C1C2C3，默认为1
 * @returns publicKey 公钥
 * @returns privateKey 私钥
 */
export async function getConfig() {
  if (!ENCRYPT) return;
  // 判断加密配置是否存在
  if ([1, 0].includes(encryptMode) && publicKey && privateKey) {
    return;
  }
  // 获取SM2配置信息
  await getSM2Config()
    .then((res) => {
      const resData = res?.data;
      encryptMode = 1; // 默认设置为1
      publicKey = resData?.publicKey;
      privateKey = resData?.privateKey;
    })
    .catch(() => {
      console.log("获取加解密配置失败！");
    });
}

/**
 * 加密数据
 * @param {Object} data 明文数据
 */
export function encryptData(data) {
  // 判断是否是字符串
  const dataType = dataTypeFun(data);
  if (!ENCRYPT) return data;
  // 判断加密配置是否存在
  if (![1, 0].includes(encryptMode) && !publicKey && !privateKey) return data;
  // 需要加密数据 类型为 number,string,boolean,undefined,null,array,object,function
  let eData = "";
  if (dataType === "object" || dataType === "array") {
    eData = JSON.stringify(data);
  } else if (dataType === "undefined" || dataType === "unll") {
    eData = "";
  } else {
    eData = String(data);
  }
  // 加密处理
  return "04".concat(sm2.doEncrypt(eData, publicKey, encryptMode));
}

/**
 * 解密数据
 * @param {Object} dataHex 加密的密文数据
 */
export function decryptData(eData) {
  if (!ENCRYPT) return eData;
  // 判断加密配置是否存在
  if (![1, 0].includes(encryptMode) && !publicKey && !privateKey) return eData;
  // 解密数据
  let dData = "";
  // 解密处理
  if (dataTypeFun(eData) === "string") {
    dData = sm2.doDecrypt(eData.slice(2), privateKey, encryptMode);
    try {
      dData = JSON.parse(dData);
    } catch (err) {
      console.log(err, "JSON.parse异常");
    }
    return dData;
  }
  return eData;
}

/**
 * 判断类型方法
 */
export const dataTypeFun = (data) => {
  // console.log(typeof 42); // "number"
  // console.log(typeof "Hello"); // "string"
  // console.log(typeof true); // "boolean"
  // console.log(typeof undefined); // "undefined"
  // console.log(typeof null); // "object"（注意这里的特殊情况）
  // console.log(typeof [1, 2, 3]); // "object"
  // console.log(typeof { foo: "bar" }); // "object"
  // console.log(typeof function () {}); // "function"
  // console.log(Object.prototype.toString.call(42)); // "[object Number]"
  // console.log(Object.prototype.toString.call("Hello")); // "[object String]"
  // console.log(Object.prototype.toString.call(true)); // "[object Boolean]"
  // console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
  // console.log(Object.prototype.toString.call(null)); // "[object Null]"
  // console.log(Object.prototype.toString.call([1, 2, 3])); // "[object Array]"
  // console.log(Object.prototype.toString.call({ foo: "bar" })); // "[object Object]"
  // console.log(Object.prototype.toString.call(function () {})); // "[object Function]"
  let dataType = typeof data;
  // 针对 object 类型做处理
  if (dataType === "object") {
    switch (Object.prototype.toString.call(data)) {
      case "[object Null]":
        dataType = "null";
        break;
      case "[object Array]":
        dataType = "array";
        break;
      case "[object Object]":
        dataType = "object";
        break;
      default:
        break;
    }
  }
  return dataType; // 类型为 number,string,boolean,undefined,null,array,object,function
};
